home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-06-15 | 11.2 KB | 212 lines | [TEXT/pdos] |
- Rez 105
- Copyright January 15, 1991 by Tim Swihart
- All Rights Reserved
-
-
- This time around, we'll focus on what's new in Part 3.5. There never was a
- public version of Part 3.4 (it got lost in a shuffle on my hard drive one day).
- The custom cursor was tossed overboard (it was put in partially just to show
- how to do it), several new icons have been added (for drawing the "levels"),
- and I've added two custom resources. The big goal of this release is to show
- custom resources - how to create them in Rez, how to use them from C
- (which makes it fairly easy to see how to do it from any language), and some
- of the things custom resources make possible. In order to show non-trivial
- custom resources, I had to add the extra icons (you want it to be at least a
- little snazzy, right?).
-
-
- One other Cleanup:
- In Part 3.3, I hard-coded the locations on the screen of the icons I was
- drawing. That means that anytime I wanted to add, delete, or reposition an
- icon I had to recompile and relink my application. Not a very pretty way to
- maintain something that should be as flexible as a game screen (you want it
- to be VERY flexible during development and sometimes afterward [Arkanoid
- II's game screen is flexible, that's why you can make custom screens for it]).
-
- In Part 3.5, the locations of all icons in the window are kept in the resource
- fork (they're part of one of the two custom resources I mentioned not long
- ago). The drawMyContents() routine simply uses the information in the
- custom resources to determine how many icons to draw and where to draw
- them at. Using the tricks we learned earlier (Rez's "-a" flag and/or the
- "include" statement in a Rez file), we don't have to rebuild the entire
- resource fork to make even major changes to the screen's layout. We only
- need to rebuild the individual custom resource that controls that icon's
- positioning. No linking is needed either (while the link times for rTutor so
- far have been short, link times on large apps are seemingly infinite - no
- matter which linker you use).
-
-
- How's It Work?
- It may sound like magic, but it's not. It's a simple application of the
- principle of data abstraction I discussed in earlier releases of this tutorial
- series. To explain how it works, I first need to explain what the custom
- resources are and how they're used. Then the "magic" becomes obvious.
-
-
- Will Custom Resource #1 Please Stand Up?
- In order to protect ourselves as much as possible from changes in our data
- (after all, icon locations are just data, right?), we need to change the way we
- draw. Instead of hard-coding everything (including how many icons we'll
- draw), why not simply use a counted list (meaning a list whose first element
- is the count of the number of items in it).
-
- This requires a custom resource I called it an rMySpotList (all resource
- names start with a lower case "r" by convention) because it's a list of "spots"
- on the screen where I want to draw. Why didn't I call it an "rPointList"
- (since a "point" is already defined as an x/y location on the screen)?
- Originally I did! But, it turned out that I wanted MORE information than just
- the x/y location, so I created a new structure that contained the info I
- needed and called it a "spot" ("rover" is over used in my opinion). Since I
- really wanted a list of "spots", I had to create the rMySpotList.
-
-
- Brief Side-Note:
- In the C source, you can find the definition for a "Spot" as well as for a
- "SpotList", but in the Rez source the "Spot" itself wasn't need and was never
- created. That means we have two custom resources, but three custom data
- structures in our C source. In C, we need the actual spot in order to get to
- its components. In Rez, we create the spots, but never access their components
- (remember, the "spot" itself exists in C so we can access its components). If
- you're lost on this point, don't sweat it -> it's a minor one. Work through
- the source files and it'll become more obvious.
-
-
- Back to Custom Resource #1:
- Rez has an easy way to produce counted lists (which made this type of
- custom resource REAL easy to create). See the Rez source and then the Rez
- manual for details on how I created the counted list in Rez (hint: read about
- "$$Countof" in the Rez manual).
-
- When it comes time to draw the icons, we simply load the rMySpotList
- resource and loop through all the spots in the list. How do we know how
- many spots are in the list? Simple, we grab the "count" off the top of the
- structure and use it as the upper boundary on our loop! That's data
- abstraction at work -> if our list grows, the count is bumped (which is PART
- of the list) and the routine still works. In essence, we're making the list
- tell us how many elements it has, then grabbing each of those elements.
-
- Since the location the icons are drawn at is part of each "spot", we can use
- larger or smaller icons and the ONLY change needed would be to tweak the
- list so the x/y locations embedded within it reflect the bigger or smaller
- icons. No change would be required in the application itself!
-
-
- So Why Do We Need The Other One?
- In Part 3.3, we simply put one icon on the screen. A "LoadRunner" style
- game needs several different icons (one for the "floor", one for the "ladder",
- etc). How do we know in advance how many icons are allow per level? Do
- we just force a limit into our C source? NO!!!
-
- Let's reflect on the lessons we just learned from the first custom resource.
- What if we had something in the resource fork that told us how many icons
- were used on a particular level? Hmmm....
-
- Wait a sec. What if we want one level to look like a land scene (floors,
- ladders, etc) and another level to look radically different? If all we know
- is how many icons are available per level, then we'd have to always use the
- same icons. Why not take this one step further?
-
- What if we created a custom resource that not only told us how many icons
- were on a given level, but what their resource ID's were? That would let us
- draw as many different icons on each level as we could ever want!
-
- And thus, custom resource #2 was born. Called an "rWhichIconsUsed"
- resource, this one is also a counted list. The count field tells us how many
- icons are used on this level and the rest of the list is the ID of each icon
- used for that level. This one is probably easier to grasp than the
- rMySpotList since its structure is much simpler.
-
- With this second structure in place, we can now modify our window content
- drawing routine to contain a nested loop. The outer loop runs through each
- icon that's going to be on the screen and the inner loop draw that icon at
- all of its locations. The end result is that we draw all of one icon, then
- all of the next, then the next, and so on. The whole thing is reasonably
- quick and if you create the list right you can force some visual effects into
- the drawing (making it appear that the screen is drawn in a right to left
- sweeping motion or top to bottom or...).
-
-
- Important Note:
- Did you catch that we're letting Rez do our counting for us? We can delete a
- random number of elements from either of these custom resources,
- recompile, and it'll work. Why? Because the "count" field is filled in by
- Rez at compile time and accurately reflects the number of elements in the list.
- This means we can also add elements freely without having to recount them
- (Rez has to recount them). Let your tools do the mundane stuff (like
- counting the number of items in a list) whenever possible.
-
-
- Can I Make These Resources With Other Tools?
- Sure, you could write a custom editor for GeneSys (Great app - do you have
- it yet? If not, you should.) but I have yet to be able to visualize a good
- interface for it. It would be fairly simple to just create a stand-alone
- desktop app that lets you pick a given icon, slam it around on the screen
- (force it to "snap" to the "grid" locations that correspond to that size icon),
- then create either the Rez source or the actual resource. Your custom app
- would have to do the counting since that value is VERY important.
- Personally, I think the easiest way to create an editor like this is with
- HyperCard IIGS, but that's a subject for another day. :-)
-
-
- Wait a Second...
- It should have occurred to you by know (no points off it it didn't though)
- that we're cramming a bunch of stuff into resource without giving much
- consideration for how we're going to tell one level's list from another's.
- For the SpotLists, we have a real problem! Each icon has to have a separate
- SpotList for EACH level. Hmmm, what if we looked at the resource ID as a
- hex number, then split the hex digits into pieces? One piece could be used to
- denote which icon it's for and another piece could be used to denote which
- level that list is for. There's a detailed comment in the Rez source for Part
- 3.5 that shows how we do this. Assembly programmers will catch on right
- away (it's just like packing bits to save space).
-
- We don't have to pull any fancy stunts for the resource ID's of the
- rWhichIconsUsed resources. There's only one of them per level, so just make
- their ID's equal the level the represent. i.e.: the rWhichIconsUsed list for
- level 1 would have a resource ID of 1, level 2's would have an ID of 2, etc.
-
-
- One More Thing:
- Speaking of data abstraction and how it can helps us minimize waste caused
- by change. The x/y locations used in Part 3.3 were hard coded and were
- based on the height and width of the icons. If we switched to different sized
- icons, every one of the x/y's had to be tweaked. What if we defined a
- constant that reflected the height (in pixels) of the icons we're using and
- another one that reflected the width (in pixels)? If we changed the icon's
- size, we'd only have to change the two constants and recompile! Much less
- work, wouldn't you agree?
-
- Look in the Rez source file at the different SpotLists. One of them is hard-
- coded and the others use the constants. Compile time for the hard-code one
- is a little faster (less math for the compiler to do), but changes are VERY
- hard. When developing software (especially stuff you expect to use over and
- over) be sure to keep an eye out for ways to do things that reduce
- "maintenance time" (the time you spend making changes, fixing bugs, etc).
- You may take a little hit on compile time, but you often will save MUCH more
- time in the long run. Don't go overboard - learn when the trade off between
- raw compile speed and ease of maintenance should be made. Trial and error
- (with forethought and some 20-20 hindsight) should be a good teacher.
-
-
- Next Time Around:
- We'll add the code to make the "player" icon move. Start thinking about the
- best way to do this (and the easiest). We don't want to have to redraw the
- entire screen on each move, just the area affected. Do we need more custom
- data structures? If so, what would they look like? (there are undoubtedly
- several correct answers here).
-
-
- On Your Own:
- The layout for level 1 that I've provided is pretty weak (I just slammed a
- bunch of numbers down in a hurry). Spend a little time laying out a real
- screen. Send it to me (email is fine) and I'll put the best of them into the
- next release. That will force you to go through what a Spot really is, how to
- create a spot list, etc. It'll also save me from having to do a better level.
- <grin>
-
-
-
-
- Enjoy,
- Tim S.
-